home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CU Amiga Super CD-ROM 17
/
CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso
/
CUCD
/
Programming
/
DiceSource
/
src
/
dc1
/
genlogic.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-09-09
|
8KB
|
349 lines
/*
* (c)Copyright 1992-1997 Obvious Implementations Corp. Redistribution and
* use is allowed under the terms of the DICE-LICENSE FILE,
* DICE-LICENSE.TXT.
*/
/*
* GENLOGIC.C
*
* logic functions like &, |, etc..
*
* WARNING: asm_shift must deal with source & dest being different sizes
* due to auto-assign
*
* NOTE: &=, |=, etc.. with lhs bit fields, CreateBinaryResult will
* bfext the lhs. It is expected that the lhs is already freed.
*/
#include "defs.h"
Prototype void GenAnd(Exp **);
Prototype void GenOr(Exp **);
Prototype void GenXor(Exp **);
Prototype void GenLShf(Exp **);
Prototype void GenRShf(Exp **);
Prototype void GenCompl(Exp **);
/*
* AND. We do not have to extend results to an integer:
*
* 0 & 0 -> 0
* 0 & 1 -> 0
* 1 & 0 -> 0
* 1 & 1 -> 1
*
* We also optimize for conditionals here. However, this does not
* work for the &= operator so we have to check
*/
void
GenAnd(pexp)
Exp **pexp;
{
Exp *exp = *pexp;
Exp *e1;
Exp *e2;
if (exp->ex_Type) {
if (exp->ex_ExpL->ex_Type == NULL)
exp->ex_ExpL->ex_Type = exp->ex_Type;
if (exp->ex_ExpR->ex_Type == NULL)
exp->ex_ExpR->ex_Type = exp->ex_Type;
}
CallLeft();
EnsureReturnStorageLeft();
if (GenPass == 0) {
if (exp->ex_Flags & EF_ASSEQ) { /* not req'd. optmizio */
Type *t = exp->ex_ExpL->ex_Type;
if (exp->ex_ExpR->ex_Type == NULL)
exp->ex_ExpR->ex_Type = t;
exp->ex_Type = t;
}
CallRight();
e1 = exp->ex_ExpL;
e2 = exp->ex_ExpR;
/*
* for conditionals, unsignedness can matter. For example,
* char a; if ((a & 0x80) < 0) ... would not work if we allowed
* the return type to be a char. (the latter example is NEVER
* less than 0 since the char is supposed to be extended first.
*
* Do not reduce return size requirements for longs to allow btst
* optimization without requiring a move
*/
if (exp->ex_Type == NULL) {
short isUnsigned = 0;
if ((e1->ex_Type->Flags | e2->ex_Type->Flags) & TF_UNSIGNED)
isUnsigned = 1;
if (e1->ex_Stor.st_Type == ST_IntConst) {
if (exp->ex_Flags & EF_COND) {
if (e1->ex_Stor.st_IntConst < 0x8000 && e2->ex_Type->Size < 4)
exp->ex_Type = e2->ex_Type;
if (e1->ex_Stor.st_IntConst < 0x80 && e2->ex_Type->Size == 1)
exp->ex_Type = e2->ex_Type;
}
}
if (e2->ex_Stor.st_Type == ST_IntConst) {
if (exp->ex_Flags & EF_COND) {
if (e2->ex_Stor.st_IntConst < 0x8000 && e1->ex_Type->Size < 4)
exp->ex_Type = e1->ex_Type;
if (e2->ex_Stor.st_IntConst < 0x80 && e1->ex_Type->Size == 1)
exp->ex_Type = e1->ex_Type;
}
}
}
BinaryLogicRules(exp);
e1 = exp->ex_ExpL;
e2 = exp->ex_ExpR;
if (e1->ex_Stor.st_Type == ST_IntConst && e2->ex_Stor.st_Type == ST_IntConst) {
e1->ex_Stor.st_IntConst = e1->ex_Stor.st_IntConst & e2->ex_Stor.st_IntConst;
*pexp = e1;
}
exp->ex_Flags |= (e1->ex_Flags | e2->ex_Flags) & EF_CALL;
} else {
CallRight();
e1 = exp->ex_ExpL;
e2 = exp->ex_ExpR;
if ((exp->ex_Flags & EF_COND) && !(exp->ex_Flags & EF_ASSEQ)) {
FreeStorage(&e1->ex_Stor);
FreeStorage(&e2->ex_Stor);
exp->ex_Flags |= EF_CONDACK;
asm_test_and(exp, &e1->ex_Stor, &e2->ex_Stor);
if (exp->ex_Cond >= 0)
asm_condbra(COND_NEQ, exp->ex_LabelT);
else
asm_condbra(COND_EQ, exp->ex_LabelF);
} else {
if (CreateBinaryResultStorage(exp, 1))
asm_and(exp, &e1->ex_Stor, &e2->ex_Stor, &exp->ex_Stor);
}
}
}
/*
* OR. We do not have to extend results to an integer:
*
* 0 | 0 -> 0
* 0 | 1 -> 1
* 1 | 0 -> 1
* 1 | 1 -> 1
*/
void
GenOr(pexp)
Exp **pexp;
{
Exp *exp = *pexp;
Exp *e1;
Exp *e2;
if (exp->ex_Type) {
if (exp->ex_ExpL->ex_Type == NULL)
exp->ex_ExpL->ex_Type = exp->ex_Type;
if (exp->ex_ExpR->ex_Type == NULL)
exp->ex_ExpR->ex_Type = exp->ex_Type;
}
CallLeft();
EnsureReturnStorageLeft();
if (GenPass == 0) {
if (exp->ex_Flags & EF_ASSEQ) { /* not req'd. optmizio */
Type *t = exp->ex_ExpL->ex_Type;
if (exp->ex_ExpR->ex_Type == NULL)
exp->ex_ExpR->ex_Type = t;
exp->ex_Type = t;
}
CallRight();
BinaryLogicRules(exp);
e1 = exp->ex_ExpL;
e2 = exp->ex_ExpR;
if (e1->ex_Stor.st_Type == ST_IntConst && e2->ex_Stor.st_Type == ST_IntConst) {
e1->ex_Stor.st_IntConst = e1->ex_Stor.st_IntConst | e2->ex_Stor.st_IntConst;
*pexp = e1;
}
exp->ex_Flags |= (e1->ex_Flags | e2->ex_Flags) & EF_CALL;
} else {
CallRight();
e1 = exp->ex_ExpL;
e2 = exp->ex_ExpR;
if (CreateBinaryResultStorage(exp, 1))
asm_or(exp, &e1->ex_Stor, &e2->ex_Stor, &exp->ex_Stor);
}
}
/*
* XOR. We do not have to extend results to an integer:
*
* 0 | 0 -> 0
* 0 | 1 -> 1
* 1 | 0 -> 1
* 1 | 1 -> 0
*/
void
GenXor(pexp)
Exp **pexp;
{
Exp *exp = *pexp;
Exp *e1;
Exp *e2;
if (exp->ex_Type) {
if (exp->ex_ExpL->ex_Type == NULL)
exp->ex_ExpL->ex_Type = exp->ex_Type;
if (exp->ex_ExpR->ex_Type == NULL)
exp->ex_ExpR->ex_Type = exp->ex_Type;
}
CallLeft();
EnsureReturnStorageLeft();
if (GenPass == 0) {
if (exp->ex_Flags & EF_ASSEQ) { /* not req'd. optmizio */
Type *t = exp->ex_ExpL->ex_Type;
if (exp->ex_ExpR->ex_Type == NULL)
exp->ex_ExpR->ex_Type = t;
exp->ex_Type = t;
}
CallRight();
BinaryLogicRules(exp);
e1 = exp->ex_ExpL;
e2 = exp->ex_ExpR;
if (e1->ex_Stor.st_Type == ST_IntConst && e2->ex_Stor.st_Type == ST_IntConst) {
e1->ex_Stor.st_IntConst = e1->ex_Stor.st_IntConst ^ e2->ex_Stor.st_IntConst;
*pexp = e1;
}
exp->ex_Flags |= (e1->ex_Flags | e2->ex_Flags) & EF_CALL;
} else {
CallRight();
e1 = exp->ex_ExpL;
e2 = exp->ex_ExpR;
if (CreateBinaryResultStorage(exp, 1))
asm_xor(exp, &e1->ex_Stor, &e2->ex_Stor, &exp->ex_Stor);
}
}
void
GenLShf(pexp)
Exp **pexp;
{
Exp *exp = *pexp;
Exp *e1;
Exp *e2;
CallLeft();
EnsureReturnStorageLeft();
CallRight();
if (GenPass == 0) {
ShiftRules(exp);
e1 = exp->ex_ExpL;
e2 = exp->ex_ExpR;
if (e1->ex_Stor.st_Type == ST_IntConst && e2->ex_Stor.st_Type == ST_IntConst) {
e1->ex_Stor.st_IntConst = e1->ex_Stor.st_IntConst << e2->ex_Stor.st_IntConst;
*pexp = e1;
}
exp->ex_Flags |= (e1->ex_Flags | e2->ex_Flags) & EF_CALL;
} else {
e1 = exp->ex_ExpL;
e2 = exp->ex_ExpR;
if (CreateBinaryResultStorage(exp, 1))
asm_shift(exp, -1, &e1->ex_Stor, &e2->ex_Stor, &exp->ex_Stor);
}
}
void
GenRShf(pexp)
Exp **pexp;
{
Exp *exp = *pexp;
Exp *e1;
Exp *e2;
CallLeft();
EnsureReturnStorageLeft();
CallRight();
if (GenPass == 0) {
ShiftRules(exp);
e1 = exp->ex_ExpL;
e2 = exp->ex_ExpR;
if (e1->ex_Stor.st_Type == ST_IntConst && e2->ex_Stor.st_Type == ST_IntConst) {
if (e1->ex_Type->Flags & TF_UNSIGNED)
e1->ex_Stor.st_IntConst = e1->ex_Stor.st_UIntConst >> e2->ex_Stor.st_UIntConst;
else
e1->ex_Stor.st_IntConst = e1->ex_Stor.st_IntConst >> e2->ex_Stor.st_IntConst;
*pexp = e1;
}
exp->ex_Flags |= (e1->ex_Flags | e2->ex_Flags) & EF_CALL;
} else {
e1 = exp->ex_ExpL;
e2 = exp->ex_ExpR;
if (CreateBinaryResultStorage(exp, 1))
asm_shift(exp, 1, &e1->ex_Stor, &e2->ex_Stor, &exp->ex_Stor);
}
}
void
GenCompl(pexp)
Exp **pexp;
{
Exp *exp = *pexp;
Exp *e1;
if (exp->ex_Type && exp->ex_ExpL->ex_Type == NULL)
exp->ex_ExpL->ex_Type = exp->ex_Type;
CallLeft();
if (GenPass == 0) {
UnaryLogicRules(exp);
e1 = exp->ex_ExpL;
if (e1->ex_Stor.st_Type == ST_IntConst) {
e1->ex_Stor.st_IntConst = ~e1->ex_Stor.st_IntConst;
*pexp = e1;
}
exp->ex_Flags |= e1->ex_Flags & EF_CALL;
} else {
Stor con;
e1 = exp->ex_ExpL;
AllocConstStor(&con, -1, exp->ex_Type);
if (CreateUnaryResultStorage(exp, 1))
asm_xor(exp, &con, &e1->ex_Stor, &exp->ex_Stor);
}
}
void
filler_gen_logic(void)
{
Assert(1);
}